import { Provide } from '@midwayjs/core'
import { Repository } from 'typeorm'
import { InjectEntityModel } from '@midwayjs/typeorm'
import { MaterialDonate } from '../../entities/MaterialDonate.entity'
import { MaterialDonateRecord } from '../../entities/MaterialDonateRecord.entity'
import { Users } from '../../entities/Users.entity'

@Provide()
export class DonateService {
  @InjectEntityModel(MaterialDonate)
  repo!: Repository<MaterialDonate>

  @InjectEntityModel(MaterialDonateRecord)
  recordRepo!: Repository<MaterialDonateRecord>

  @InjectEntityModel(Users)
  userRepo!: Repository<Users>

  // 获取需要捐赠的物资列表
  async getDonateList(page: number = 1, pageSize: number = 10) {
    // 创建查询构建器，使用实体关系来联查物资捐赠记录统计捐助人数和已捐赠数量
    const queryBuilder = this.repo.createQueryBuilder('md')
      .leftJoin('md.material', 'm')
      .leftJoin('md.donateRecords', 'mdr')
      .select([
        'md.id AS id',
        'md.createTime AS createTime',
        'md.count AS count',
        'md.price AS price',
        'md.title AS title',
        'md.materialId AS materialId',
        'm.name AS materialName',
        'm.description AS materialDescription',
        'm.category AS materialCategory',
        'm.tag AS materialTag',
        'm.img AS materialImg',
        'COUNT(DISTINCT mdr.userId) AS donorCount',
        'COALESCE(SUM(mdr.count), 0) AS totalDonated'
      ])
      .groupBy('md.id, md.createTime, md.count, md.price, md.title, md.materialId, m.name, m.description, m.category, m.tag, m.img')
      .orderBy('md.createTime', 'DESC')

    // 获取总数（需要单独查询，因为有 GROUP BY）
    const countQuery = this.repo.createQueryBuilder('md')
    const total = await countQuery.getCount()
    
    // 获取分页数据
    const items = await queryBuilder
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getRawMany()

    // 计算捐赠进度
    const itemsWithProgress = items.map(item => ({
      ...item,
      donationProgress: item.count > 0 ? Math.min((item.totalDonated / item.count) * 100, 100) : 0,
      remainingCount: Math.max(item.count - item.totalDonated, 0)
    }))

    return {
      total,
      items: itemsWithProgress,
    }
  }

  // 获取单个捐赠物资详情
  async getDonateDetail(id: number) {
    const queryBuilder = this.repo.createQueryBuilder('md')
      .leftJoin('md.material', 'm')
      .leftJoin('md.donateRecords', 'mdr')
      .select([
        'md.id AS id',
        'md.createTime AS createTime',
        'md.count AS count',
        'md.price AS price',
        'md.title AS title',
        'md.materialId AS materialId',
        'm.name AS materialName',
        'm.description AS materialDescription',
        'm.category AS materialCategory',
        'm.tag AS materialTag',
        'm.img AS materialImg',
        'm.price AS materialPrice',
        'COUNT(DISTINCT mdr.userId) AS donorCount',
        'COALESCE(SUM(mdr.count), 0) AS totalDonated'
      ])
      .where('md.id = :id', { id })
      .groupBy('md.id, md.createTime, md.count, md.price, md.title, md.materialId, m.name, m.description, m.category, m.tag, m.img, m.price')

    const donate = await queryBuilder.getRawOne()

    if (!donate) {
      throw new Error('捐赠物资不存在')
    }

    // 计算捐赠进度和剩余数量
    const donationProgress = donate.count > 0 ? Math.min((donate.totalDonated / donate.count) * 100, 100) : 0
    const remainingCount = Math.max(donate.count - donate.totalDonated, 0)

    return {
      ...donate,
      donationProgress,
      remainingCount
    }
  }

  // 添加捐赠记录
  async addDonateRecord(data: {
    userId: number
    materialDonateId: number
    count: number
  }) {
    // 先检查捐赠需求是否存在
    const materialDonate = await this.repo.findOne({
      where: { id: data.materialDonateId }
    })

    if (!materialDonate) {
      throw new Error('捐赠需求不存在')
    }

    // 检查已捐赠数量
    const totalDonatedResult = await this.recordRepo.createQueryBuilder('mdr')
      .select('COALESCE(SUM(mdr.count), 0)', 'totalDonated')
      .where('mdr.materialDonateId = :materialDonateId', { materialDonateId: data.materialDonateId })
      .getRawOne()

    const totalDonated = parseInt(totalDonatedResult.totalDonated) || 0
    const needCount = materialDonate.count || 0
    const remainingCount = needCount - totalDonated

    // 检查捐赠数量是否超过剩余需求
    if (data.count > remainingCount) {
      throw new Error(`捐赠数量不能超过剩余需求数量(${remainingCount})`)
    }

    // 创建捐赠记录
    const record = this.recordRepo.create({
      userId: data.userId,
      materialDonateId: data.materialDonateId,
      count: data.count
    })

    const savedRecord = await this.recordRepo.save(record)

    // 更新用户证书类型，添加捐赠证书标识"2"
    await this.updateUserCertificateTypes(data.userId, '2')

    return savedRecord
  }

  // 更新用户证书类型
  private async updateUserCertificateTypes(userId: number, certificateType: string) {
    const user = await this.userRepo.findOne({ where: { id: userId.toString() } })
    
    if (!user) {
      return
    }

    let certificateTypes = user.certificateTypes || ''
    const typesArray = certificateTypes ? certificateTypes.split(',') : []
    
    // 如果该类型不存在，则添加
    if (!typesArray.includes(certificateType)) {
      typesArray.push(certificateType)
      certificateTypes = typesArray.join(',')
      
      await this.userRepo.update(userId.toString(), { certificateTypes })
    }
  }

  // 获取用户的捐赠记录
  async getUserDonateRecords(userId: number, page: number = 1, pageSize: number = 10) {
    const queryBuilder = this.recordRepo.createQueryBuilder('mdr')
      .leftJoin('mdr.materialDonate', 'md')
      .leftJoin('md.material', 'm')
      .leftJoin('mdr.user', 'u')
      .select([
        'mdr.id AS id',
        'mdr.createTime AS createTime',
        'mdr.count AS count',
        'mdr.materialDonateId AS materialDonateId',
        'mdr.userId AS userId',
        'md.title AS donateTitle',
        'm.name AS materialName',
        'm.description AS materialDescription',
        'm.category AS materialCategory',
        'm.tag AS materialTag',
        'm.img AS materialImg',
        'u.nickname AS userNickname',
        'u.phone AS userPhone'
      ])
      .where('mdr.userId = :userId', { userId })
      .orderBy('mdr.createTime', 'DESC')

    // 获取总数
    const total = await queryBuilder.getCount()
    
    // 获取分页数据
    const items = await queryBuilder
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getRawMany()

    return {
      total,
      items,
    }
  }

  // 获取捐赠需求的捐赠记录列表
  async getDonateRecordsByDonateId(materialDonateId: number, page: number = 1, pageSize: number = 10) {
    const queryBuilder = this.recordRepo.createQueryBuilder('mdr')
      .leftJoin('mdr.user', 'u')
      .select([
        'mdr.id AS id',
        'mdr.createTime AS createTime',
        'mdr.count AS count',
        'mdr.userId AS userId',
        'u.nickname AS userNickname',
        'u.avatar AS userAvatar'
      ])
      .where('mdr.materialDonateId = :materialDonateId', { materialDonateId })
      .orderBy('mdr.createTime', 'DESC')

    // 获取总数
    const total = await queryBuilder.getCount()
    
    // 获取分页数据
    const items = await queryBuilder
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getRawMany()

    return {
      total,
      items,
    }
  }

  // 检查用户是否有捐赠记录，并返回最近一次捐赠时间
  async checkUserHasDonated(userId: number): Promise<{ hasDonated: boolean; lastDonateTime: Date | null }> {
    const latestRecord = await this.recordRepo.findOne({
      where: { userId },
      order: { createTime: 'DESC' }
    })
    
    return {
      hasDonated: !!latestRecord,
      lastDonateTime: latestRecord?.createTime || null
    }
  }
}